using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Text;
using System.Xml;
using System.Windows.Forms;
using System.IO;
using Athena.Objects;
using Athena.Tools;

using WeifenLuo.WinFormsUI.Docking;

namespace Athena
{

    public partial class DrawPanel : DockContent 
    {
        internal const string VISUALEDITOR_FORMAT = "visualeditor-items";

        public enum State
        {
            None,
            Drawing,
            Connecting,
            Selecting,
            Modifying
        }

        private Model _oCurrentModel = Program.Model;

        internal Model CurrentModel
        {
            get { return _oCurrentModel; }
            set { _oCurrentModel = value; }
        }


        internal ToolStripItem[] DefaultContextMenuItems
        {
            get
            {
                return new System.Windows.Forms.ToolStripItem[] {
                    this.copyToolStripMenuItem,
                    this.cutToolStripMenuItem,
                    this.pasteToolStripMenuItem,
                    this.duplicateToolStripMenuItem,
                    this.deleteToolStripMenuItem
                };
            }

        }

        private State _CurrentState = State.None;

        public State CurrentState
        {
            get { return _CurrentState; }
            set
            {
                if (_CurrentState == value) return;
                _CurrentState = value;
                pnlCanvas.Invalidate();
            }
        }

        private PointF _Last = new PointF();
        private Corner _lastCorner = Corner.None;
        private IDrawable _lastSelected = null;
        long delta = 0;

        public DrawPanel()
        {
            InitializeComponent();

            // set up missing icons
            this.copyToolStripMenuItem.Image = ((System.Drawing.Image)(MainForm.Resources.GetObject("copyToolStripButton.Image")));
            this.cutToolStripMenuItem.Image = ((System.Drawing.Image)(MainForm.Resources.GetObject("cutToolStripButton.Image")));
            this.pasteToolStripMenuItem.Image = ((System.Drawing.Image)(MainForm.Resources.GetObject("pasteToolStripButton.Image")));

            Text = "Canvas";
            pnlCanvas.BindScrollbars(vScrollBar1, hScrollBar1);

        }

        public void NewDocument()
        {
            HistoryManager.History.SetControllPoint("New Document");
            CurrentModel.Clear(true);
            CurrentModel.DefaultFileName = "";
            Program.Form.Text = "Athena : Untitled"; 
            CurrentState = State.None;
        }


        private PointF GetTransformedPoint(PointF point)
        {
            return pnlCanvas.GetTransformedPoint(point);
        }

        long _lastMouseDownTick = 0;
        
        private void pnlCanvas_MouseDown(object sender, MouseEventArgs e)
        {
            pnlCanvas.Focus();
            _lastMouseDownTick = DateTime.Now.Ticks;
            PointF location = GetTransformedPoint(e.Location);

            HandledMouseEventArgs args = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false);
            ToolManager.Instance.OnMouseDown(args);

            if (args.Handled)
            {
                _Last = location;
                CurrentState = State.None;
                pnlCanvas.Refresh();
                return;
            }


            if (e.Button == MouseButtons.Left)
            {
                switch (CurrentState)
                {
                    case State.Modifying:
                        {
                            if (ModifierKeys != Keys.Shift) CurrentModel.DeselectItems();
                            List<IDrawable> oItems = CurrentModel.FindItems(location);
                            if (oItems.Count == 0)
                            {

                                CurrentState = State.Selecting;
                            }
                        }
                        break;
                    case State.Selecting:
                        {
                            _Last = location;

                            if (CurrentModel.Selected.Count > 0)
                            {
                                if (_lastSelected == null)
                                    _lastSelected = CurrentModel.Selected[0];
                                _lastCorner = _lastSelected.Where(location);
                                if (_lastCorner != Corner.None)
                                {
                                    HistoryManager.History.BeginRecord("Resizing Selected");
                                    CurrentState = State.Modifying;
                                    break;
                                }
                            }

                            if (ModifierKeys != Keys.Shift) CurrentModel.DeselectItems(false);
                            List<IDrawable> oItems = CurrentModel.FindItems(location);
                            if (ModifierKeys == Keys.Shift)
                                CurrentModel.ToggleSelection(oItems,false);
                            if (oItems.Count > 0)
                            {
                                _lastSelected = oItems[oItems.Count - 1];
                                CurrentModel.SelectItem(_lastSelected,false);                                
                                CurrentState = State.None;
                            }
                            CurrentModel.OnSelectionChanged(new Model.SelectionEventArgs(CurrentModel.Selected));
                        }
                        break;
                    case State.None:
                        {
                            _Last = location;
                            /*if (ModifierKeys == (Keys.Shift | Keys.Control))
                            {
                                List<IDrawable> oItems = CurrentModel.FindItems(location);
                                this.DoDragDrop(oItems, DragDropEffects.Copy);
                            }
                            else*/
                            {
                                HistoryManager.History.BeginRecord("Moving Selected");

                                if (CurrentModel.Selected.Count > 0)
                                {
                                    if (_lastSelected == null)
                                        _lastSelected = CurrentModel.Selected[0];
                                    _lastCorner = _lastSelected.Where(location);
                                    if (_lastCorner != Corner.None)
                                    {
                                        HistoryManager.History.BeginRecord("Resizing Selected");
                                        CurrentState = State.Modifying;
                                        break;
                                    }
                                }

                                if (ModifierKeys != Keys.Shift) CurrentModel.DeselectItems(false);
                                List<IDrawable> oItems = CurrentModel.FindItems(location);
                                if (oItems.Count == 0)
                                {
                                    CurrentState = State.Selecting;
                                }
                                if (oItems.Count > 0)
                                {
                                    _lastSelected = oItems[oItems.Count - 1];
                                    if (ModifierKeys == Keys.Shift && _lastSelected.IsSelected)
                                        CurrentModel.DeselectItem(_lastSelected,false);
                                    else
                                        CurrentModel.SelectItem(_lastSelected,false);
                                }
                                CurrentModel.OnSelectionChanged(new Model.SelectionEventArgs(CurrentModel.Selected));
                            }
                        }
                        break;
                    default:
                        {
                            break;
                        }
                }

            }
            else if (e.Button == MouseButtons.Right)
            {
                if (CurrentModel.Selected.Count < 1)
                {
                    List<IDrawable> oItems = CurrentModel.FindItems(location);

                    if (oItems.Count > 0)
                    {
                        //CurrentModel.SelectItems(oItems);
                        CurrentModel.SelectItem(oItems[oItems.Count - 1]);
                    }
                }

                mnuItems.Items.Clear();
                mnuItems.Items.AddRange(DefaultContextMenuItems);
                ToolManager.Instance.SetupContextMenu(mnuItems, CurrentModel.SelectedTypes);
                mnuItems.Show(MousePosition);
            }

            pnlCanvas.Invalidate();
        }

        void pnlCanvas_MouseDoubleClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            PointF location = GetTransformedPoint(e.Location);
            HandledMouseEventArgs args = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false);
            ToolManager.Instance.OnItemDoubleClick(args);
            if (args.Handled)
            {
                _Last = location;
                pnlCanvas.Refresh();
                return;
            }
        }

        private void pnlCanvas_MouseUp(object sender, MouseEventArgs e)
        {
            PointF location = GetTransformedPoint(e.Location);
            HandledMouseEventArgs args = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false);
            ToolManager.Instance.OnMouseUp(args);
            if (args.Handled)
            {
                _Last = location;
                pnlCanvas.Refresh();
                return;
            }

            try
            {
                switch (CurrentState)
                {
                    case State.Modifying:
                        CurrentModel.InformCollision(CurrentModel.Selected);
                        for (int i = 0; i < CurrentModel.Selected.Count; ++i)
                            CurrentModel.Selected[i].DoneModifying(_lastCorner,true);                        
                        HistoryManager.History.EndRecord();
                        CurrentState = State.None;
                        pnlCanvas.Refresh();
                        break;
                    case State.Selecting:
                        List<IDrawable> oItems = CurrentModel.FindItems(pnlCanvas.SelectRectangle);

                        if (ModifierKeys != Keys.Shift)
                        {
                            CurrentModel.DeselectItemsNotIn(oItems, false);
                        }                            

                        CurrentModel.ToggleSelection(oItems, true);

                        pnlCanvas.SelectRectangle = RectangleF.Empty;
                        pnlCanvas.Refresh();
                        break;
                    case State.None:
                        CurrentModel.InformCollision(CurrentModel.Selected);
                        for (int i = 0; i < CurrentModel.Selected.Count; ++i)
                            CurrentModel.Selected[i].DoneModifying(_lastCorner,true);                        
                        HistoryManager.History.EndRecord();
                        pnlCanvas.Refresh();
                        break;
                    default:
                        //for (int i = 0; i < CurrentModel.Selected.Count; ++i)
                        //    CurrentModel.Selected[i].DoneModifying();
                        break;
                }
            }
            catch (Exception)
            {
            }


        }
        private void pnlCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (!_bAllowHover)
            {
                _bAllowHover = true;
            }

            if (DateTime.Now.Ticks - _lastMouseDownTick < 100) return;
            PointF location = GetTransformedPoint(e.Location);
            HandledMouseEventArgs args = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false);
            ToolManager.Instance.OnMouseMove(args);
            if (args.Handled)
            {
                pnlCanvas.Refresh();
                _Last = location;
                return;
            }



            if (e.Button != 0)
            {

                switch (CurrentState)
                {
                    case State.Modifying:
                        {
                            if (_lastSelected != null)
                            {
                                PointF relative = Utility.GetRelative(location, _Last);
                                _lastSelected.Transform(relative, ref _lastCorner, ModifierKeys == Keys.Control);
                                _Last = location;
                            }
                            pnlCanvas.Invalidate();
                            break;
                        }
                    case State.Selecting:
                        {
                            HistoryManager.History.ClearRecord();

                            /*List<IDrawable> oItems = CurrentModel.FindItems(pnlCanvas.SelectRectangle);

                            if (ModifierKeys != Keys.Shift)
                            {
                                CurrentModel.DeselectItemsNotIn(oItems);
                            }*/
                            PointF relative = Utility.GetRelative(location, _Last);
                            float x = (relative.X > 0 ? _Last.X : _Last.X + relative.X);
                            float y = (relative.Y > 0 ? _Last.Y : _Last.Y + relative.Y);
                            float w = Math.Abs(_Last.X - location.X);
                            float h = Math.Abs(_Last.Y - location.Y);
                            pnlCanvas.SelectRectangle = new RectangleF(x, y, w, h);
                            
                            //CurrentModel.SelectItems(oItems);

                            pnlCanvas.Refresh();
                            break;
                        }
                    default:
                        MoveSelectedRelative(Utility.GetRelative(location, _Last));
                        //for (int i = 0; i < CurrentModel.Selected.Count; ++i)
                        //    CurrentModel.Selected[i].DoneModifying();
                        _Last = location;
                        pnlCanvas.Invalidate();
                        break;
                }
            }
            else
            {
                if (ShowQuickTip && TimeSpan.FromTicks(DateTime.Now.Ticks - delta).Milliseconds > 900)
                {
                    delta = DateTime.Now.Ticks;
                    //ShowToolTip();
                }
            }
        }



        private bool _bShowQuickTip = false;

        [Description("if true, a quicktip will be displayed over an object, when a user hovers over it for 900ms"), Category("")]
        public bool ShowQuickTip
        {
            get { return _bShowQuickTip; }
            set { _bShowQuickTip = value; }
        }


        private void pnlCanvas_MouseLeave(object sender, EventArgs e)
        {
            _oToolTip.SetToolTip(pnlCanvas, "");
            _oToolTip.ToolTipTitle = "";
            pnlCanvas.Invalidate();
        }

        void Zoom(int nDelta)
        {
            if (nDelta < 0)
            {
                pnlCanvas.ScaleFactor *= 0.9f; ;
            }
            else
            {
                pnlCanvas.ScaleFactor *= 1.1f;
            }
            pnlCanvas.Invalidate();
        }

        void ScrollUpDown(int nDelta)
        {
            if (nDelta < 0)
            {
                pnlCanvas.ScrollDown();
            }
            else
            {
                pnlCanvas.ScrollUp();
            }
            pnlCanvas.Invalidate();
        }

        public void DeleteSelected()
        {
            CurrentModel.DeleteSelected();
        }

        private void SelectNextDrawable()
        {
            if (CurrentModel.Drawables.Count == 0) return;

            if (_lastSelected == null)
            {
                _lastSelected = CurrentModel.Drawables[0];
            }
            else
            {
                if (ModifierKeys != Keys.Shift)
                {
                    CurrentModel.DeselectItem(_lastSelected);
                }
                int nIndex = CurrentModel.Drawables.IndexOf(_lastSelected);
                if ((ModifierKeys & Keys.Control) == Keys.Control)
                {
                    if (nIndex >= 1)
                        _lastSelected = CurrentModel.Drawables[nIndex - 1];
                    else
                        _lastSelected = CurrentModel.Drawables[CurrentModel.Drawables.Count - 1];
                }
                else
                {
                    if (nIndex >= 0 && nIndex < CurrentModel.Drawables.Count - 1)
                        _lastSelected = CurrentModel.Drawables[nIndex + 1];
                    else
                        _lastSelected = CurrentModel.Drawables[0];
                }

            }

            CurrentModel.SelectItem(_lastSelected);
            pnlCanvas.Invalidate();
        }

        private void DrawPanel_KeyDown(object sender, KeyEventArgs e)
        {

            //if (!Focused) return;

            ToolManager.Instance.OnKeyDown(e);

            if (e.Handled) return;

            switch (e.KeyCode)
            {
                case Keys.Delete:
                    DeleteSelected();
                    e.Handled = true;
                    break;
                case Keys.Up:
                    MoveSelectedUp();
                    e.Handled = true;
                    break;
                case Keys.Down:
                    MoveSelectedDown();
                    e.Handled = true;
                    break;
                case Keys.Left:
                    MoveSelectedLeft();
                    e.Handled = true;
                    break;
                case Keys.Right:
                    MoveSelectedRight();
                    e.Handled = true;
                    break;
                case Keys.Tab:
                    SelectNextDrawable();
                    e.Handled = true;
                    break;
                case Keys.Shift:
                case Keys.ShiftKey:
                    e.Handled = true;
                    break;
                case Keys.Escape:
                    CurrentModel.DeselectItems();
                    pnlCanvas.Invalidate();
                    e.Handled = true;
                    break;
                case Keys.A:
                    if (ModifierKeys == Keys.Control)
                    {
                        CurrentModel.SelectAllItems();
                        pnlCanvas.Invalidate();
                    }
                    e.Handled = true;
                    break;
                case Keys.D:
                    if (ModifierKeys == Keys.Control)
                    {
                        Duplicate();
                        e.Handled = true;
                    }
                    break;
                case Keys.C:
                    if (ModifierKeys == Keys.Control)
                    {
                        Copy();
                        e.Handled = true;
                    }
                    break;
                case Keys.V:
                    if (ModifierKeys == Keys.Control)
                    {
                        Paste();
                        e.Handled = true;
                    }
                    break;
                case Keys.X:
                    if (ModifierKeys == Keys.Control)
                    {
                        Cut();
                        e.Handled = true;
                    }
                    break;
                case Keys.Y:
                    if (ModifierKeys == Keys.Control)
                    {
                        HistoryManager.History.Redo();
                    }
                    break;
                case Keys.Z:
                    if (ModifierKeys == Keys.Control)
                    {
                        HistoryManager.History.Undo();
                    }
                    break;
                case Keys.F5:
                    pnlCanvas.FitToView();
                    break;
                default:
                    break;
            }
        }

        private void DrawPanel_KeyUp(object sender, KeyEventArgs e)
        {
            //if (!Focused) return;
            ToolManager.Instance.OnKeyUp(e);
            if (e.Handled) return;
        }

        void DrawPanel_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            //if (!Focused) return;
            if (e.Delta != 0)
            {
                if ((ModifierKeys & Keys.Control) == Keys.Control)
                {
                    Zoom(e.Delta / 120);
                }
                else
                {
                    ScrollUpDown(e.Delta / 120);
                }
            }
        }


        private void MoveSelectedUp()
        {
            if ((ModifierKeys & Keys.Control) == Keys.Control)
                MoveSelectedRelative(new PointF(0, -Utility.GetMaxStepY()));

            else
                MoveSelectedRelative(new PointF(0, -1));
        }

        private void MoveSelectedDown()
        {
            if ((ModifierKeys & Keys.Control) == Keys.Control)
                MoveSelectedRelative(new PointF(0, Utility.GetMaxStepY()));
            else
                MoveSelectedRelative(new PointF(0, 1));
        }

        private void MoveSelectedLeft()
        {
            if ((ModifierKeys & Keys.Control) == Keys.Control)
                MoveSelectedRelative(new PointF(-Utility.GetMaxStepX(), 0));
            else
                MoveSelectedRelative(new PointF(-1, 0));
        }

        private void MoveSelectedRight()
        {
            if ((ModifierKeys & Keys.Control) == Keys.Control)
                MoveSelectedRelative(new PointF(Utility.GetMaxStepX(), 0));

            else
                MoveSelectedRelative(new PointF(1, 0));
        }

        private void MoveSelectedRelative(PointF direction)
        {
            MoveRelative(CurrentModel.Selected, direction);
            pnlCanvas.Invalidate();
        }

        private void MoveRelative(List<IDrawable> list, PointF direction)
        {
            PointF previousRemainder = oRemainder;
            foreach (IDrawable d in list)
            {
                oRemainder = previousRemainder;
                MoveRelative(d, direction,true);
            }
        }
        private PointF oRemainder = new PointF();

        private void MoveRelative(IDrawable drawable, PointF direction, bool dFudge)
        {
            float x = drawable.Location.X + direction.X ;
            float y = drawable.Location.Y + direction.Y ;
            PointF oNewRelative = new PointF(x, y);
            if (dFudge) Utility.AddPoints(oNewRelative, oRemainder);
            PointF oNextGrid = Utility.ModifyPoint(oNewRelative);
            if (dFudge) oRemainder = Utility.SubtractPoints(oNewRelative, oNextGrid);
            drawable.MoveTo(oNextGrid);
            CurrentModel.InformMotion(drawable);
        }

        private void MoveRelative(IDrawable drawable, PointF direction)
        {
            MoveRelative(drawable, direction, true);
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DeleteSelected();
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Copy();
        }

        private void cutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Cut();
        }

        private void duplicateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Duplicate();
        }

        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Paste();
        }

        internal void Copy()
        {
            List<IDrawable> oSelected = CurrentModel.Selected;
            if (oSelected == null || oSelected.Count == 0) return;

            foreach (IDrawable d in oSelected)
                d.Deselect();

            DataFormats.Format oFormat = DataFormats.GetFormat(VISUALEDITOR_FORMAT);

            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            MemoryStream oStream = new MemoryStream();
            formatter.Serialize(oStream, oSelected);

            DataObject oDataObject = new DataObject(oFormat.Name, oStream.ToArray());



            try
            {
                RectangleF oBoundsF = Utility.GetBounds(oSelected);
                RectangleF oBoundsFGrown = oBoundsF; oBoundsFGrown.Inflate(10f, 10f);
                Rectangle oBounds = Rectangle.Round(oBoundsFGrown);
                Bitmap oImage = new Bitmap(oBounds.Width * 3 + 10, oBounds.Height * 3 + 10);

                Graphics g = Graphics.FromImage(oImage);
                g.TranslateTransform(-oBoundsF.X * 3f + 5f, -oBoundsF.Y * 3f + 5F);
                g.ScaleTransform(3f, 3f);
                g.Clear(Color.White);
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
                pnlCanvas.RenderCanvas(g, oSelected, false);

                oDataObject.SetImage(oImage);
            }
            catch (Exception)
            {
                //nevermind
            }
            foreach (IDrawable d in oSelected)
            {
                d.Select();
                if (d.Item is Core.Module)   //copy module script
                {
                    oDataObject.SetText(oDataObject.GetText() + ((Core.Module)d.Item).JarnacScript + Environment.NewLine);
                }
            }
            Clipboard.SetDataObject(oDataObject);
        }

        internal void Duplicate()
        {
            //Copy();
            //Paste();
            foreach (IDrawable drawable in CurrentModel.Selected)
            {
                IDrawable alias = drawable.GenerateAlias();
                alias.MoveTo(Utility.AddPoints(drawable.Location, new PointF(20, 20)));
                alias.DoneModifying(Corner.None,true);
                CurrentModel.Drawables.Add(alias);
                if (alias is Objects.ContainerGlyph)
                {
                    ((Objects.ContainerGlyph)alias).AddDrawablesToModel(CurrentModel);
                }
                foreach (IDrawable id in alias.AnchoredItems)
                {
                    CurrentModel.Drawables.Add(id);
                }
            }
            Utility.Refresh();
        }

        internal void Cut()
        {
            Copy();
            DeleteSelected();
            pnlCanvas.Invalidate();
        }

        internal void Paste()
        {
            if (!Clipboard.ContainsData(VISUALEDITOR_FORMAT)) return;

            CurrentModel.DeselectItems();
            IDataObject oDataObject = Clipboard.GetDataObject();

            byte[] oBuffer = (byte[])oDataObject.GetData(VISUALEDITOR_FORMAT);

            if (oBuffer == null) return;

            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

            MemoryStream oStream = new MemoryStream(oBuffer);
            List<IDrawable> oItems = (List<IDrawable>)formatter.Deserialize(oStream);

            if (oItems != null && oItems.Count > 0)
            {
                foreach (IDrawable item in oItems)
                {
                    item.Location = Utility.AddPoints(item.Location, new PointF(5f, 5f));
                    CurrentModel.AddToModel(item,false);
                    CurrentModel.SelectItem(item,false);
                }
            }
            pnlCanvas.Invalidate();
        }

        private void bringToFrontToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Utility.BringItemsToFront(CurrentModel.Selected, CurrentModel);
        }

        private void sendToBackToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Utility.SendItemsToBack(CurrentModel.Selected, CurrentModel);
        }

        private bool ShowToolTipOnSelected()
        {
            if (CurrentModel.Selected.Count < 1) return false;
            IDrawable drawable = CurrentModel.Selected[CurrentModel.Selected.Count - 1];
            PointF location = GetTransformedPoint(pnlCanvas.PointToClient(MousePosition));
            Corner corner = drawable.Where(location);
            if (corner == Corner.None) return false;
            try
            {
                drawable.ShowCornerToolTip(_oToolTip, pnlCanvas, location, corner);
            }
            catch (Exception)
            {
            }
            return _oToolTip.Active = true;
        }

        /// <summary>
        /// Show the toop tip
        /// </summary>
        /// <returns></returns>
        private bool ShowToolTip()
        {
            PointF p = pnlCanvas.PointToClient(MousePosition);
            PointF location = GetTransformedPoint(p);
            List<IDrawable> oItems = CurrentModel.FindItems(location);
            if (oItems.Count == 0)
            {
                _oToolTip.Active = false;
                return false;
            }
            IDrawable oItem = oItems[oItems.Count - 1];
            try
            {
                oItem.ShowToolTip(_oToolTip, pnlCanvas, location);
                return _oToolTip.Active = true;
            }
            catch (Exception)
            {
            }
            return (_oToolTip.Active = false);

            //_oToolTip.Active = false;
            //_oToolTip.SetToolTip(pnlCanvas,
            //    String.Format(
            //                "The object under the cursor is: "
            //              + "{2}{0},"
            //              + "{2}and it is currently {1}. "
            //              + "{2}"
            //              + "{2}Position:  \t({3},{4})"
            //              + "{2}Dimension: \t{5}x{6}"
            //              + "{2}Item:      \t{7}/{8}",
            //    oItem.ToString(),
            //    (oItem.IsSelected ? "selected" : "not selected"),
            //    "\r\n",
            //    oItem.Location.X,
            //    oItem.Location.Y,
            //    oItem.Dimensions.Width,
            //    oItem.Dimensions.Height,
            //    CurrentModel.Drawables.IndexOf(oItem) + 1,
            //CurrentModel.Drawables.Count));
            //_oToolTip.Active = true;
        }

        private void DrawPanel_DragOver(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop,false))
            {
                e.Effect = DragDropEffects.Copy;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }

            /*if (!e.Data.GetDataPresent(typeof(System.String)))
            {

                e.Effect = DragDropEffects.None;
                return;
            }

            string sData = (string)e.Data.GetData(typeof(string));
            if (Athena.Core.PartsRegistry.Instance.IsPart(sData))
            {
                e.Effect = DragDropEffects.Copy;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }*/
        }

        /// <summary>
        /// Drag and drop model files or plugin files onto the draw panel
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DrawPanel_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Effect == DragDropEffects.Copy)
            {
                string[] sFileNames = (string[])e.Data.GetData(DataFormats.FileDrop);

                if (sFileNames == null || sFileNames.Length < 0) return;

                HistoryManager.History.SetControllPoint("File dropped");

                foreach (string sFile in sFileNames)
                {

                    FileInfo oInfo = new FileInfo(sFile);
                    switch (oInfo.Extension.ToLower())
                    {
                        case ".dll":
                            try
                            {
                                PluginManager.Instance.AddPluginsFromFile(sFile);
                            }
                            catch (Exception)
                            {
                                Utility.SetMessage("Error importing plugin");
                            }
                            break;
                        default:
                            try
                            {
                                PointF p = Utility.GetTransformedPoint(new PointF((float)e.X, (float)e.Y));

                                int numDrawables = CurrentModel.Drawables.Count;

                                if (sFileNames.Length < 2)
                                {
                                    CurrentModel.DeselectItems(false);
                                    Model newModel = CurrentModel.GetModel(sFile);
                                    if (newModel == null || newModel.BackEndModel == null)
                                    {
                                        Utility.SetMessage("Error loading file");
                                        return;
                                    }

                                    string text = "Do you want to clear the current model?"
                                                  + Environment.NewLine +
                                                  "(selecting no will load the file as a module)";

                                    if (newModel.BackEndModel.LocalItems.Count == 1 &&
                                        newModel.BackEndModel.LocalItems[0].Drawable != null)  //file is a single module
                                    {
                                        IDrawable module = newModel.BackEndModel.LocalItems[0].Drawable;
                                        CurrentModel.AddToModel(module, false, false, false, false);
                                        module.MoveTo(new PointF(p.X - module.Dimensions.Width / 2f, p.Y - module.Dimensions.Height));
                                    }
                                    else
                                    {
                                        if (numDrawables > 0)
                                        {
                                            DialogResult dialogResult = MessageBox.Show(text, "Load new Model", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                                            if (dialogResult == DialogResult.Cancel)
                                                return;

                                            if (dialogResult == DialogResult.Yes)
                                            {
                                                CurrentModel.Clear(false);
                                                newModel.Clear(false);
                                                newModel = CurrentModel.GetModel(sFile);
                                                CurrentModel.BackEndModel = newModel.BackEndModel;
                                                CurrentModel.Drawables = newModel.Drawables;
                                                CurrentModel.BackEndModel.ID = oInfo.Name;
                                                //CurrentModel.DefaultFileName = sFile;
                                                Program.Form.Text = "Athena : " + sFile;
                                            }
                                            else
                                            {
                                                Core.Module module = newModel.BackEndModel;
                                                module.GenerateDrawable(Utility.DrawPanel.Location);
                                                module.ID = oInfo.Name.Remove(oInfo.Name.Length - oInfo.Extension.Length, oInfo.Extension.Length);
                                                CurrentModel.AddToModel(module.Drawable, false, false, false, true);
                                                module.Drawable.MoveTo(new PointF(p.X - module.Drawable.Dimensions.Width / 2f, p.Y - module.Drawable.Dimensions.Height));
                                            }
                                        }
                                        else
                                        {
                                            CurrentModel.BackEndModel = newModel.BackEndModel;
                                            CurrentModel.Drawables = newModel.Drawables;
                                            CurrentModel.BackEndModel.ID = oInfo.Name.Remove(oInfo.Name.Length - oInfo.Extension.Length,oInfo.Extension.Length);
                                            //CurrentModel.DefaultFileName = sFile;
                                            Program.Form.Text = "Athena : " + sFile;
                                        }
                                    }                                   
                                }
                                else
                                {
                                    CurrentModel.DeselectItems(false);
                                    Model newModel = CurrentModel.GetModel(sFile);

                                    if (newModel.BackEndModel.LocalItems.Count == 1 &&
                                        newModel.BackEndModel.LocalItems[0].Drawable != null)  //file is a single module
                                    {
                                        IDrawable module = newModel.BackEndModel.LocalItems[0].Drawable;
                                        CurrentModel.AddToModel(module, false, false, false, false);
                                        module.MoveTo(new PointF(p.X - module.Dimensions.Width / 2f, p.Y - module.Dimensions.Height));
                                    }
                                    else
                                    {
                                        Core.Module module = newModel.BackEndModel;
                                        module.GenerateDrawable(new PointF());
                                        CurrentModel.AddToModel(module.Drawable, false, false, false, false);
                                        module.Drawable.MoveTo(new PointF(p.X - module.Drawable.Dimensions.Width / 2f, p.Y - module.Drawable.Dimensions.Height));
                                    }
                                }
                                CurrentModel.OnModelChanged(EventArgs.Empty);
                                Utility.Refresh();
                            }
                            catch (Exception)
                            {
                                Utility.SetMessage("Error reading file");
                            }
                            break;
                    }

                }
            }

            /*if (e.Data.GetDataPresent(typeof(System.String)))
            {

                string item = (string)e.Data.GetData(typeof(System.String));

                // Perform drag-and-drop, depending upon the effect.
                if (e.Effect == DragDropEffects.Copy)
                {

                    Utility.SetMessage("Add Part " + item + " to canvas");
                    HistoryManager.History.SetControllPoint("Inserting Part");
                    Point oPoint = pnlCanvas.PointToClient(new Point(e.X, e.Y));
                    PointF oTarget = pnlCanvas.GetTransformedPoint(new PointF(oPoint.X, oPoint.Y));
                    CurrentModel.DeselectItems();
                    IDrawable drawable = (IDrawable) Athena.Core.PartsRegistry.Instance.GetDrawable(item, oTarget).Clone();
                    CurrentModel.AddToModel(drawable,false);
                    
                    pnlCanvas.Refresh();


                }
            }*/

        }

        bool _bAllowHover = false;

        private void pnlCanvas_MouseHover(object sender, EventArgs e)
        {
            if (ShowQuickTip && _bAllowHover) 
            {
                if (TimeSpan.FromTicks(DateTime.Now.Ticks - delta).Milliseconds > 100)
                {
                    //delta = DateTime.Now.Ticks;
                    if (!ShowToolTipOnSelected())
                    {
                        if (TimeSpan.FromTicks(DateTime.Now.Ticks - delta).Milliseconds > 500)
                        {
                            _bAllowHover = !ShowToolTip();
                        }
                    }
                    else
                    {
                        _bAllowHover = false;
                    }
                }
                
            }
            pnlCanvas.ExposedResetMouseEventArgs(); 
        }

        private void pnlCanvas_Enter(object sender, EventArgs e)
        {
            Focus();
        }
    }
}
